# Load in data
hires_2019_clean <- read_csv('../clean_data/hires_2019_clean.csv')
Rows: 124446 Columns: 19
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr   (4): start_station_name, start_station_description, end_station_name, end_station_description
dbl  (11): duration, start_station_id, start_station_latitude, start_station_longitude, end_station_id, end_station_l...
date  (2): start_date, end_date
time  (2): start_time, end_time

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
rain_2019_clean <- read_csv('../clean_data/rain_2019_clean.csv')
Rows: 365 Columns: 2
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl  (1): rainfall_mm
date (1): start_date

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
glimpse(hires_2019_clean)
Rows: 124,446
Columns: 19
$ start_date                <date> 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, …
$ start_time                <time> 05:58:47, 06:02:13, 06:14:09, 06:25:08, 06:54:31, 07:31:24, 08:47:46, 08:48:06, 09:0…
$ end_date                  <date> 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, 2019-01-01, …
$ end_time                  <time> 07:16:14, 07:21:17, 07:21:57, 06:36:22, 06:59:52, 07:42:31, 09:00:57, 09:36:29, 09:3…
$ duration                  <dbl> 77.43, 79.07, 67.80, 11.23, 5.33, 11.12, 13.18, 48.37, 24.80, 81.05, 47.33, 15.42, 58…
$ start_station_id          <dbl> 259, 259, 251, 358, 251, 261, 259, 257, 358, 284, 257, 257, 257, 257, 257, 253, 246, …
$ start_station_name        <chr> "St Andrew Square", "St Andrew Square", "Waverley Station", "Leith Walk", "Waverley S…
$ start_station_description <chr> "North East corner", "North East corner", "Platform level near Calton Road Exit", "Le…
$ start_station_latitude    <dbl> 55.95475, 55.95475, 55.95264, 55.96504, 55.95264, 55.96093, 55.95475, 55.95700, 55.96…
$ start_station_longitude   <dbl> -3.192774, -3.192774, -3.187527, -3.176686, -3.187527, -3.181005, -3.192774, -3.11688…
$ end_station_id            <dbl> 285, 285, 285, 284, 261, 265, 246, 344, 257, 257, 284, 257, 225, 256, 256, 246, 247, …
$ end_station_name          <chr> "Ocean Terminal", "Ocean Terminal", "Ocean Terminal", "Leith Links", "Brunswick Place…
$ end_station_description   <chr> "Debenhams / Puregym entrance", "Debenhams / Puregym entrance", "Debenhams / Puregym …
$ end_station_latitude      <dbl> 55.98129, 55.98129, 55.98129, 55.96920, 55.96093, 55.93981, 55.93900, 55.93640, 55.95…
$ end_station_longitude     <dbl> -3.176351, -3.176351, -3.176351, -3.166885, -3.181005, -3.182739, -3.173924, -3.19425…
$ rainfall_mm               <dbl> 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0…
$ start_elevation           <dbl> 76.04, 76.04, 57.10, 20.96, 57.10, 33.11, 76.04, 4.30, 20.96, 15.45, 4.30, 4.30, 4.30…
$ end_elevation             <dbl> 7.30, 7.30, 7.30, 15.45, 33.11, 80.45, 88.97, 94.55, 4.30, 4.30, 15.45, 4.30, 53.83, …
$ elevation_diff            <dbl> -68.74, -68.74, -49.80, -5.51, -23.99, 47.34, 12.93, 90.25, -16.66, -11.15, 11.15, 0.…
# visualising use by month
hires_2019_clean %>% 
  mutate(month = month(start_date, label = TRUE), .before = 1) %>% 
  group_by(month) %>% 
  summarise(count = n()) %>%
  ggplot() +
  aes(x = month, y = count) +
  geom_col(fill = "#F27F1B") +
  geom_text(aes(label = count), vjust = 2, colour = "white", size = 3.5) +
  labs(x = "\nMonth",
       y = "Number of journeys\n",
       title = "Total number of bike journeys by month (2019)",
       subtitle = "Total = 124446 journeys\n\n") +
  scale_y_discrete(expand = c(0,1), limits = c(0, 5000, 10000, 15000)) +
  theme_minimal() +
  theme(title = element_text(size = 12),
        axis.text = element_text(size = 10),
        axis.title.x = element_text(size = 10),
        axis.title.y = element_text(size = 10),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        panel.background = element_blank(), 
        axis.line = element_line(colour = "black"))

Mapping out stations

# create smaller dataset for map
map_data <- hires_2019_clean %>% 
  select(start_station_longitude, start_station_latitude, start_station_id, start_station_name, start_elevation) %>% 
  distinct(start_station_id, .keep_all = TRUE)

# create custom icon for bike hire stations
bike  <-  makeIcon("../www/bicycle-outline.png")

# map station data using leaflet app
map_data %>% 
  leaflet() %>% 
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addTiles(providers$CartoDB.Positron) %>%
  addMarkers(~start_station_longitude, ~start_station_latitude, 
             icon = ~bike,
             #clusterOptions = markerClusterOptions(),
             popup = ~paste0("Station ID: ", start_station_id,
                              "<br>Name: ", start_station_name,
                              "<br>Elevation (m): ", start_elevation))

  # addCircles(lng = ~start_station_longitude,
  #            lat = ~start_station_latitude,
  #            color = "#F27F1B",
  #            popup = ~paste0("Station ID: ", start_station_id,
  #                            "<br>Name: ", start_station_name,
  #                            "<br>Elevation (m): ", start_elevation))

Journeys based on elevation

68622 downhill journeys 43774 uphill journeys 12050 flat journeys

12050 / 124446 * 100
[1] 9.682915

Journeys based on weather

According to www.statista.com “A rainday is when one millimetre or more of rain occurs in a day.” Based on this I have classified rainy days as days where rainfall as recorded by www.power.larc.nasa.gov/ was equal to or over 1mm in Edinburgh.

Hypothesis Test

# calculate the p-value and compare to α value
p_value <- null_distribution %>%
  get_p_value(obs_stat = observed_stat, direction = "left")
Warning: Please be cautious in reporting a p-value of 0. This result is an approximation based on the number of `reps` chosen in the `generate()` step. See `?get_p_value()` for more information.
# hypothesis test
# α = 0.05
# H0 - Rain makes no difference to bike hires
# H1 - Rain has an impact on bike hires
# Type of test is one-sample proportion, right-sided.
# 
# p value = 0 
# 
# The p-value being near to 0 means it is less than α, and so we should reject H0 based on our data. The result is statistically significant in favour of H1, that rain may impact bike hire numbers.

# rain_day <- hires_2019_clean %>%
#   group_by(start_date) %>% 
#   mutate(rain_day = rainfall_mm >= 1) %>% 
#   select(start_date, rain_day) %>% 
#   count(start_date, rain_day)
# 
# null_distribution <- rain_day %>%
#   specify(response = rain_day, success = "TRUE") %>%
#   hypothesize(null = "point", p = 0.05) %>%
#   generate(reps = 10000, type = "draw") %>%
#   calculate(stat = "prop")
# 
# obs_stat <- rain_day %>%
#   specify(response = rain_day, success = "TRUE") %>%
#   calculate(stat = "prop")
# 
# null_distribution %>%
#   visualise() +
#   shade_p_value(direction = "right", obs_stat = obs_stat)
# 
# null_distribution %>%
#   get_p_value(direction = "right", obs_stat = obs_stat)
# bootstrapped hypothesis
# α = 0.05
# H0 - Rain makes no difference to bike hires
# H1 - Rain has an impact on bike hires

# rain_day_flag <- rain_day %>%
#   mutate(rain_day_flag = if_else(rain_day == "TRUE", 1, 0))
# 
# null_distribution <- rain_day_flag %>%
#   specify(response = rain_day_flag) %>%
#   hypothesize(null = "point", mu = 0.05) %>%
#   generate(reps = 10000, type = "bootstrap") %>%
#   calculate(stat = "mean")
# 
# null_distribution %>%
#   visualise() +
#   shade_p_value(direction = "right", obs_stat = obs_stat)
# 
# null_distribution %>%
#   get_p_value(direction = "right", obs_stat = obs_stat)

Independence Hypothesis Test On Rainy day data

Does a rainy day have an effect on bike hires

α = 0.05 H0 - Rain makes no difference to bike hires H1 - Rain has an impact on bike hires

The p-value ≤ α, so I reject the null hypothesis H0 in favour of the alternative hypothesis H1, that rain may have an effect on bike hires.

Rainy Days in 2019 = 181 Rainy journeys = 58073 (46.7%) Non rainy journeys = 66373 (53.3%)

66373 / 124446 * 100
[1] 53.33478

Time of Day analysis

Gym Bunnies - 5am to 7am: 2419 17.54 mins
Morning Commuters - 7am to 9am: 12452 17.87 mins
Day Trippers - 9am to 5pm: 66880 29.75 mins
Homeward Bounders - 5pm to 6.30pm: 14961 23.86 mins
Evening Movers - 6.30pm to 10pm: 16815 23.50 mins
Pub Ponies - 10pm to 5am: 10919 23.07 mins

Average journey time overall is 26.18 minutes

Most popular hour is from 4pm to 5pm 12279 journeys average time 24.27 mins.

hires_2019_clean %>% 
  select(start_time) %>%
  group_by(start_time) %>% 
  count() %>%
  ggplot() +
  geom_histogram(aes(start_time), col = "white", fill = "#F27F1B") +
  labs(x = "\nTime of Day",
       y = "Number of Journeys\n",
       title = "Start time of journeys") +
  theme_minimal() +
  theme(title = element_text(size = 12),
        axis.text = element_text(size = 10),
        axis.title.x = element_text(size = 10),
        axis.title.y = element_text(size = 10),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        panel.background = element_blank(), 
        axis.line = element_line(colour = "black"))
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

hires_2019_clean %>% 
  mutate(start_hour = hour(start_time), .before = 2) %>% 
  group_by(start_hour) %>% 
  count(start_hour) %>% 
  ggplot() +
  #geom_rect(aes(xmin=0, xmax=7, ymin=0, ymax=Inf), fill = "#F27F1B", alpha = 0.1) +
  # annotate("rect", xmin = 0, xmax = 5, ymin = 0, ymax = Inf, fill = "#5A4FF5", alpha = .9) +
  # annotate("rect", xmin = 5, xmax = 7, ymin = 0, ymax = Inf, fill = "#FFFB85", alpha = .7) +
  # annotate("rect", xmin = 7, xmax = 9, ymin = 0, ymax = Inf, fill = "#FFE930", alpha = .6) +
  # annotate("rect", xmin = 9, xmax = 17, ymin = 0, ymax = Inf, fill = "#F27F1B", alpha = .4) +
  # annotate("rect", xmin = 17, xmax = 18.5, ymin = 0, ymax = Inf, fill = "#DE6DCC", alpha = .4) +
  # annotate("rect", xmin = 18.5, xmax = 22, ymin = 0, ymax = Inf, fill = "#9D84F5", alpha = .7) +
  # annotate("rect", xmin = 22, xmax = 23, ymin = 0, ymax = Inf, fill = "#5A4FF5", alpha = .9) +
  geom_point(aes(start_hour, n), color = "#F27F1B") +
  geom_line(aes(start_hour, n), color = "#F27F1B", alpha = 0.5) +
    labs(x = "\nStart hour",
       y = "Number of Journeys\n",
       title = "START TIME OF JOURNEYS\n") +
  scale_x_discrete(expand = c(0,.5), limits = c(0:23)) +
  theme_minimal() +
  theme(title = element_text(size = 12, family="Proxima Nova", face = "bold"),
        axis.text = element_text(size = 10, family="Proxima Nova", face = "bold", colour = "#8C8C8C"),
        axis.title.x = element_text(size = 10, colour = "#8C8C8C"),
        axis.title.y = element_text(size = 10, colour = "#8C8C8C"),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        panel.background = element_blank(), 
        axis.line = element_line(colour = "#8C8C8C"))
Warning: Continuous limits supplied to discrete scale.
Did you mean `limits = factor(...)` or `scale_*_continuous()`?

# trying a raster image of elevation

edi <- st_read('../raw_data/Edinburgh_Ward_Boundaries/Edinburgh_Ward_Boundaries.shp', "Edinburgh_Ward_Boundaries")

st_union(edi)
ggplot() +
  geom_raster(data = new_elevation_raster, aes(x = x, y = y)) +
  geom_sf(data = edi, color = "red") +
  coord_sf() +
  scale_fill_viridis_c() +
  labs(title = " ", x = " ", y = " ", fill = " ")
Warning: Raster pixels are placed at uneven vertical intervals and will be shifted. Consider using geom_tile() instead.

plot(elevation_raster, 
     main = "Elevation levels across Edinburgh in metres",
     key = "map_data")
Warning in plot.window(...) : "key" is not a graphical parameter
Warning in plot.xy(xy, type, ...) : "key" is not a graphical parameter
Warning in axis(side = side, at = at, labels = labels, ...) :
  "key" is not a graphical parameter
Warning in axis(side = side, at = at, labels = labels, ...) :
  "key" is not a graphical parameter
Warning in box(...) : "key" is not a graphical parameter
Warning in title(...) : "key" is not a graphical parameter

LS0tCnRpdGxlOiAiRmluYWwgUHJvamVjdCB3b3JrYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKYGBge3IgaW5jbHVkZT1GQUxTRX0KIyBsb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkobGVhZmxldCkKbGlicmFyeShlbGV2YXRyKQpsaWJyYXJ5KHJnZGFsKQpsaWJyYXJ5KGNpcmNsaXplKQpsaWJyYXJ5KGdncmFwaCkKbGlicmFyeShpbmZlcikKbGlicmFyeShzZikKbGlicmFyeShyZ2VvYm91bmRhcmllcykKbGlicmFyeShtYXBkZWNrKQpsaWJyYXJ5KHJhc3RlcikKCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRX0KIyBMb2FkIGluIGRhdGEKaGlyZXNfMjAxOV9jbGVhbiA8LSByZWFkX2NzdignLi4vY2xlYW5fZGF0YS9oaXJlc18yMDE5X2NsZWFuLmNzdicpCnJhaW5fMjAxOV9jbGVhbiA8LSByZWFkX2NzdignLi4vY2xlYW5fZGF0YS9yYWluXzIwMTlfY2xlYW4uY3N2JykKCmdsaW1wc2UoaGlyZXNfMjAxOV9jbGVhbikKYGBgCgoKCmBgYHtyfQojIG51bWJlciBvZiBzdGF0aW9ucyBpbiB0b3RhbDogMTY0CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGRpc3RpbmN0KHN0YXJ0X3N0YXRpb25faWQpICU+JSAKICBjb3VudCgpCgpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBkaXN0aW5jdChlbmRfc3RhdGlvbl9pZCkgJT4lIAogIGNvdW50KCkKYGBgCgoKYGBge3J9CiMgdmlzdWFsaXNpbmcgdXNlIGJ5IG1vbnRoCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIG11dGF0ZShtb250aCA9IG1vbnRoKHN0YXJ0X2RhdGUsIGxhYmVsID0gVFJVRSksIC5iZWZvcmUgPSAxKSAlPiUgCiAgZ3JvdXBfYnkobW9udGgpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IG1vbnRoLCB5ID0gY291bnQpICsKICBnZW9tX2NvbChmaWxsID0gIiNGMjdGMUIiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvdW50KSwgdmp1c3QgPSAyLCBjb2xvdXIgPSAid2hpdGUiLCBzaXplID0gMy41KSArCiAgbGFicyh4ID0gIlxuTW9udGgiLAogICAgICAgeSA9ICJOdW1iZXIgb2Ygam91cm5leXNcbiIsCiAgICAgICB0aXRsZSA9ICJUb3RhbCBudW1iZXIgb2YgYmlrZSBqb3VybmV5cyBieSBtb250aCAoMjAxOSkiLAogICAgICAgc3VidGl0bGUgPSAiVG90YWwgPSAxMjQ0NDYgam91cm5leXNcblxuIikgKwogIHNjYWxlX3lfZGlzY3JldGUoZXhwYW5kID0gYygwLDEpLCBsaW1pdHMgPSBjKDAsIDUwMDAsIDEwMDAwLCAxNTAwMCkpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpCgpgYGAKCmBgYHtyfQojIHZpc3VhbGlzZSB1c2UgYnkgZGF5IG9mIHRoZSB3ZWVrCgpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoZGF5ID0gd2RheShzdGFydF9kYXRlLCBsYWJlbCA9IFRSVUUpLCAuYmVmb3JlID0gMSkgJT4lIAogIGdyb3VwX2J5KGRheSkgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gZGF5LCB5ID0gY291bnQpICsKICBnZW9tX2NvbChmaWxsID0gIiNGMjdGMUIiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGNvdW50KSwgdmp1c3QgPSAyLCBjb2xvdXIgPSAid2hpdGUiLCBzaXplID0gMy41KSArCiAgbGFicyh4ID0gIlxuRGF5IG9mIHdlZWsiLAogICAgICAgeSA9ICJOdW1iZXIgb2Ygam91cm5leXNcbiIsCiAgICAgICB0aXRsZSA9ICJUb3RhbCBudW1iZXIgb2YgYmlrZSBqb3VybmV5cyBieSBkYXkgb2Ygd2VlayAoMjAxOSkiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAsMSksIGxpbWl0cyA9IGMoMCwgNTAwMCwgMTAwMDAsIDE1MDAwKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKYGBgCgoKIyMjIE1hcHBpbmcgb3V0IHN0YXRpb25zCgpgYGB7cn0KIyBjcmVhdGUgc21hbGxlciBkYXRhc2V0IGZvciBtYXAKbWFwX2RhdGEgPC0gaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgc2VsZWN0KHN0YXJ0X3N0YXRpb25fbG9uZ2l0dWRlLCBzdGFydF9zdGF0aW9uX2xhdGl0dWRlLCBzdGFydF9zdGF0aW9uX2lkLCBzdGFydF9zdGF0aW9uX25hbWUsIHN0YXJ0X2VsZXZhdGlvbikgJT4lIAogIGRpc3RpbmN0KHN0YXJ0X3N0YXRpb25faWQsIC5rZWVwX2FsbCA9IFRSVUUpCmBgYAoKCmBgYHtyfQoKIyBjcmVhdGUgY3VzdG9tIGljb24gZm9yIGJpa2UgaGlyZSBzdGF0aW9ucwpiaWtlICA8LSAgbWFrZUljb24oIi4uL3d3dy9iaWN5Y2xlLW91dGxpbmUucG5nIikKCiMgbWFwIHN0YXRpb24gZGF0YSB1c2luZyBsZWFmbGV0IGFwcAptYXBfZGF0YSAlPiUgCiAgbGVhZmxldCgpICU+JSAKICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSAlPiUgCiAgYWRkVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JQogIGFkZE1hcmtlcnMofnN0YXJ0X3N0YXRpb25fbG9uZ2l0dWRlLCB+c3RhcnRfc3RhdGlvbl9sYXRpdHVkZSwgCiAgICAgICAgICAgICBpY29uID0gfmJpa2UsCiAgICAgICAgICAgICAjY2x1c3Rlck9wdGlvbnMgPSBtYXJrZXJDbHVzdGVyT3B0aW9ucygpLAogICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUwKCJTdGF0aW9uIElEOiAiLCBzdGFydF9zdGF0aW9uX2lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPk5hbWU6ICIsIHN0YXJ0X3N0YXRpb25fbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5FbGV2YXRpb24gKG0pOiAiLCBzdGFydF9lbGV2YXRpb24pKQoKICAjIGFkZENpcmNsZXMobG5nID0gfnN0YXJ0X3N0YXRpb25fbG9uZ2l0dWRlLAogICMgICAgICAgICAgICBsYXQgPSB+c3RhcnRfc3RhdGlvbl9sYXRpdHVkZSwKICAjICAgICAgICAgICAgY29sb3IgPSAiI0YyN0YxQiIsCiAgIyAgICAgICAgICAgIHBvcHVwID0gfnBhc3RlMCgiU3RhdGlvbiBJRDogIiwgc3RhcnRfc3RhdGlvbl9pZCwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+TmFtZTogIiwgc3RhcnRfc3RhdGlvbl9uYW1lLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5FbGV2YXRpb24gKG0pOiAiLCBzdGFydF9lbGV2YXRpb24pKQpgYGAKCiMjIyBNb3N0IHBvcHVsYXIgc3RhdGlvbnMKCgpgYGB7cn0KIyB0b3AgMTAgc3RhcnQgYW5kIGVuZCBzdGF0aW9ucwpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBzZWxlY3Qoc3RhcnRfc3RhdGlvbl9pZCwgc3RhcnRfc3RhdGlvbl9uYW1lLCBzdGFydF9zdGF0aW9uX2Rlc2NyaXB0aW9uLCBzdGFydF9lbGV2YXRpb24pICU+JSAKICBjb3VudChzdGFydF9zdGF0aW9uX2lkLCBzdGFydF9zdGF0aW9uX25hbWUsIHN0YXJ0X3N0YXRpb25fZGVzY3JpcHRpb24sIHN0YXJ0X2VsZXZhdGlvbikgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSkgJT4lIAogIGhlYWQoMTApCgpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBzZWxlY3QoZW5kX3N0YXRpb25faWQsIGVuZF9zdGF0aW9uX25hbWUsIGVuZF9zdGF0aW9uX2Rlc2NyaXB0aW9uLCBlbmRfZWxldmF0aW9uKSAlPiUgCiAgY291bnQoZW5kX3N0YXRpb25faWQsIGVuZF9zdGF0aW9uX25hbWUsIGVuZF9zdGF0aW9uX2Rlc2NyaXB0aW9uLCBlbmRfZWxldmF0aW9uKSAlPiUgCiAgYXJyYW5nZShuKSAlPiUKICBoZWFkKDEwKQpgYGAKCgpgYGB7cn0KIyByb3VuZCB0cmlwIHZzIGEgdG8gYiBqb3VybmV5CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihzdGFydF9zdGF0aW9uX2lkID09IGVuZF9zdGF0aW9uX2lkKSAlPiUgCiAgY291bnQoKQoKMTE5NDQgLyAxMjQ0NDYgKiAxMDAgIyA5LjYlIG9mIGpvdXJuZXlzIHdlcmUgcm91bmQgdHJpcHMKCiMgbW9zdCBwb3B1bGFyIHJvdW5kIHRyaXAgc3RhdGlvbnMKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgPT0gZW5kX3N0YXRpb25faWQpICU+JSAKICBjb3VudChzdGFydF9zdGF0aW9uX2lkKSAlPiUgCiAgYXJyYW5nZShkZXNjKG4pKQoKIyB2aXN1YWxpc2Ugcm91bmQgdHJpcCB2cyBvbmUgd2F5cwpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUocm91bmRfdHJpcHMgPSBzdGFydF9zdGF0aW9uX2lkID09IGVuZF9zdGF0aW9uX2lkKSAlPiUgCiAgY291bnQocm91bmRfdHJpcHMpICU+JSAKICBnZ3Bsb3QoKSArCiAgYWVzKHJvdW5kX3RyaXBzLCBuKSArCiAgZ2VvbV9jb2woZmlsbCA9ICIjRjI3RjFCIikgKwogIGxhYnMoeCA9ICJcbk9uZSBXYXkgdnMgUm91bmQgVHJpcCIsCiAgICAgICB5ID0gIk51bWJlciBvZiBqb3VybmV5c1xuIiwKICAgICAgIHRpdGxlID0gIk9uZSBXYXkgdnMgUm91bmQgVHJpcCBqb3VybmV5cyB0YWtlbiIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpCgpgYGAKCgpgYGB7cn0KIyBtYXAgbW9zdCBwb3B1bGFyIHN0YXRpb25zIGRhdGEgdXNpbmcgbGVhZmxldCBhcHAKbWFwX2RhdGEgJT4lIAogIGZpbHRlcihzdGFydF9zdGF0aW9uX2lkICVpbiUgYygiMjQ4IiwgIjI1OSIsICIyNjUiLCAiMjg5IiwgIjI1NyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyNDkiLCAiMjQ3IiwgIjE3MSIsICIxODMiLCAiMjYyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjI1MCIsICIzNTgiLCAiMjU4IikpICU+JQogIGxlYWZsZXQoKSAlPiUgCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lIAogIGFkZFRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSAlPiUKICBhZGRNYXJrZXJzKH5zdGFydF9zdGF0aW9uX2xvbmdpdHVkZSwgfnN0YXJ0X3N0YXRpb25fbGF0aXR1ZGUsIAogICAgICAgICAgICAgaWNvbiA9IH5iaWtlLAogICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUwKCJTdGF0aW9uIElEOiAiLCBzdGFydF9zdGF0aW9uX2lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+TmFtZTogIiwgc3RhcnRfc3RhdGlvbl9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+RWxldmF0aW9uIChtKTogIiwgc3RhcnRfZWxldmF0aW9uKSkKCmBgYAoKYGBge3J9Cm1hcF9kYXRhICU+JSAKICBmaWx0ZXIoc3RhcnRfc3RhdGlvbl9pZCAlaW4lIGMoIjI0OCIsICIyNTkiLCAiMjY1IiwgIjI4OSIsICIyNTciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjI0OSIsICIyNDciLCAiMTcxIiwgIjE4MyIsICIyNjIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjI1MCIsICIzNTgiLCAiMjU4IikpICU+JSAKICBnZ3Bsb3QobGFiZWwgPSBzdGFydF9zdGF0aW9uX2lkKSArCiAgZ2VvbV9wb2ludChhZXMoc3RhcnRfc3RhdGlvbl9pZCwgc3RhcnRfZWxldmF0aW9uKSkgKwogIHRoZW1lX2J3KCkgKwogIGdlb21fdGV4dChhZXMoc3RhcnRfc3RhdGlvbl9pZCwgc3RhcnRfZWxldmF0aW9uLCBsYWJlbCA9IHN0YXJ0X2VsZXZhdGlvbiwgaGp1c3Q9LTAuMiwgdmp1c3Q9MCkpCgpgYGAKCmBgYHtyfQojIGNyZWF0ZSBhIG1hcCBvZiBqb3VybmV5cyBzcGVjaWZpZWQgaW4gdGhlIGZpbHRlcigpIGFyZ3VtZW50LCBhcmNzIHNob3cgc3RhcnQgYW5kIHN0b3AgcG9pbnRzLAojIGhvdmVyaW5nIG92ZXIgYW4gYXJjIHNob3dzIHRoZSBlbGV2YXRpb24gZGlmZmVyZW5jZSBiZXR3ZWVuIHN0YXJ0IGFuZCBlbmQgcG9pbnRzCmxpYnJhcnkobWFwZGVjaykKCnNldF90b2tlbigicGsuZXlKMUlqb2lhbUkzTkNJc0ltRWlPaUpqYkRONE5tNTJPR013WjNwbk0yTnhkSGhsTVRoeGFuQTBJbjAuaUZOY09ndVU2cmtVUUVoR3J1cVNCZyIpICAjIyBzZXQgeW91ciBtYXBib3ggdG9rZW4gaGVyZQojc2V0X3Rva2VuKCJway5leUoxSWpvaWFtSTNOQ0lzSW1FaU9pSmpiRE40Tm01Mk9HTXdaM3BuTTJOeGRIaGxNVGh4YW5BMEluMC5pRk5jT2d1VTZya1VRRWhHcnVxU0JnIikgICMjIHNldCB5b3VyIG1hcGJveCB0b2tlbiBoZXJlCgojbWFwZGVja190b2tlbnMoKQoKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCmZpbHRlcihzdGFydF9zdGF0aW9uX2lkICVpbiUgYygiMjQ4IikpICU+JSAKICBuYS5vbWl0KCkgJT4lIAptYXBkZWNrKHN0eWxlID0gbWFwZGVja19zdHlsZSgnZGFyaycpLCBwaXRjaCA9IDQ1LAogICAgICAgIGxvY2F0aW9uID0gYyg1NS45NDIsIC0zLjE5OSkpJT4lCiAgYWRkX2FyYygKICAgICAgbGF5ZXJfaWQgPSAnYXJjX2xheWVyJwogICAgLCBvcmlnaW4gPSBjKCJzdGFydF9zdGF0aW9uX2xvbmdpdHVkZSIsICJzdGFydF9zdGF0aW9uX2xhdGl0dWRlIikKICAgICwgZGVzdGluYXRpb24gPSBjKCJlbmRfc3RhdGlvbl9sb25naXR1ZGUiLCAiZW5kX3N0YXRpb25fbGF0aXR1ZGUiKQogICAgLCBzdHJva2VfZnJvbV9vcGFjaXR5ID0gMTAwCiAgICAsIHN0cm9rZV90b19vcGFjaXR5ID0gMTAwCiAgICAsIHN0cm9rZV93aWR0aCA9IDMKICAgICwgc3Ryb2tlX2Zyb20gPSAiI0YyN0YxQiIKICAgICwgc3Ryb2tlX3RvID0gIiNGMjdGMUIiCiAgICAsIHRvb2x0aXAgPSAiZWxldmF0aW9uX2RpZmYiCiAgKQoKIyIyNTkiLCAiMjY1IiwgIjI4OSIsICIyNTciLCAiMjQ5IiwgIjI0NyIsICIxNzEiLCAiMTgzIiwgIjI2MiIsICIyNTAiLCAiMzU4IiwgIjI1OCIKYGBgCmBgYHtyfQpoaXJlc18yMDE5X2NsZWFuICU+JSAKZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgJWluJSBjKCIyNDgiKSkgJT4lIAogIG5hLm9taXQoKSAlPiUgCm1hcGRlY2soc3R5bGUgPSBtYXBkZWNrX3N0eWxlKCdkYXJrJyksIHBpdGNoID0gNDUsCiAgICAgICAgbG9jYXRpb24gPSBjKDU1Ljk0MiwgLTMuMTk5KSklPiUKICBhZGRfbGluZSgKICAgICAgbGF5ZXJfaWQgPSAnYXJjX2xheWVyJwogICAgLCBvcmlnaW4gPSBjKCJzdGFydF9zdGF0aW9uX2xvbmdpdHVkZSIsICJzdGFydF9zdGF0aW9uX2xhdGl0dWRlIikKICAgICwgZGVzdGluYXRpb24gPSBjKCJlbmRfc3RhdGlvbl9sb25naXR1ZGUiLCAiZW5kX3N0YXRpb25fbGF0aXR1ZGUiKQogICAgLCBzdHJva2Vfd2lkdGggPSAzCiAgICAsIHN0cm9rZV9jb2xvdXIgID0gIiNGMjdGMUIiCiAgICAsIHN0cm9rZV9vcGFjaXR5ICA9IDAuMwogICAgLCB0b29sdGlwID0gImVsZXZhdGlvbl9kaWZmIgogICkKYGBgCgoKYGBge3J9CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIHNlbGVjdChzdGFydF9zdGF0aW9uX2lkLCBlbmRfc3RhdGlvbl9pZCkgJT4lIAogIGZpbHRlcihzdGFydF9zdGF0aW9uX2lkID09IGMoIjI0OCIsICIyNTkiLCAiMjY1IiwgIjI4OSIsICIyNTciLCAiMjYyIiwgIjI0OSIsICIyNDciLCAiMTcxIiwgIjE4MyIpLCAKICAgICAgICAgZW5kX3N0YXRpb25faWQgPT0gYygiMjYyIiwgIjI1NyIsICIyNTAiLCAiMjY1IiwgIjI0OCIsICIzNTgiLCAiMjU5IiwgIjE4MyIsICIxNzEiLCAiMjU4IikpICU+JSAKICBjaG9yZERpYWdyYW0oc2NhbGUgPSBUUlVFKQogIApgYGAKCmBgYHtyfQojIEpvdXJuZXlzIGVuZGluZyBhdCBWaWN0b3JpYSBRdWF5CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihlbmRfc3RhdGlvbl9pZCA9PSAiMjUwIikgJT4lIAogIGNvdW50KCkKCiMgSm91cm5leXMgZW5kaW5nIGF0IFZpY3RvcmlhIFF1YXksIGJ5IHN0YXJ0IHN0YXRpb24KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKGVuZF9zdGF0aW9uX2lkID09ICIyNTAiKSAlPiUgCiAgY291bnQoc3RhcnRfc3RhdGlvbl9pZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSkKCiMgSm91cm5leXMgZW5kaW5nIGF0IEdlb3JnZSBTcXVhcmUsIGJ5IHN0YXJ0IHN0YXRpb24KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKGVuZF9zdGF0aW9uX2lkID09ICIxNzEiKSAlPiUgCiAgY291bnQoc3RhcnRfc3RhdGlvbl9pZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSkKCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihzdGFydF9zdGF0aW9uX2lkID09ICIyNTkiKSAlPiUgCiAgY291bnQoZW5kX3N0YXRpb25faWQpICU+JSAKICBhcnJhbmdlKGRlc2MobikpCmBgYAoKCgpgYGB7cn0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgc2VsZWN0KHN0YXJ0X3N0YXRpb25faWQsIGVuZF9zdGF0aW9uX2lkKSAlPiUKICBmaWx0ZXIoc3RhcnRfc3RhdGlvbl9pZCA9PSBjKCIyNDgiLCAiMjU5IiwgIjI2NSIsICIyODkiLCAiMjU3IiwgIjI2MiIsICIyNDkiLCAiMjQ3IiwgIjE3MSIsICIxODMiKSwgCiAgICAgICAgIGVuZF9zdGF0aW9uX2lkID09IGMoIjI2MiIsICIyNTciLCAiMjUwIiwgIjI2NSIsICIyNDgiLCAiMzU4IiwgIjI1OSIsICIxODMiLCAiMTcxIiwgIjI1OCIpKSAlPiUgCiAgZ2dyYXBoKGxheW91dCA9ICJsaW5lYXIiKSArIAogIGdlb21fZWRnZV9hcmMoZWRnZV9jb2xvdXIgPSAiYmxhY2siLCBlZGdlX2FscGhhID0gMC4zLCBlZGdlX3dpZHRoID0gMC4yKSArCiAgZ2VvbV9ub2RlX3BvaW50KGNvbG9yID0gIiNGMjdGMUIiLCBzaXplID0gMTApICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgcmVwZWwgPSBGQUxTRSwgc2l6ZSA9IDMsIG51ZGdlX3kgPSAwLCBjb2xvdXIgPSAid2hpdGUiKSArCiAgbGFicyh0aXRsZSA9ICJKb3VybmV5cyBiZXR3ZWVuIG1vc3QgcG9wdWxhciBzdGF0aW9uc1xuXG4iKSArCiAgdGhlbWVfdm9pZCgpICsKICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQocmVwKDEsIDQpLCAiY20iKSkKYGBgCgoKIyMjIEpvdXJuZXlzIGJhc2VkIG9uIGVsZXZhdGlvbgoKNjg2MjIgZG93bmhpbGwgam91cm5leXMKNDM3NzQgdXBoaWxsIGpvdXJuZXlzCjEyMDUwIGZsYXQgam91cm5leXMKCmBgYHtyfQojIGRvd25oaWxsIHZzIHVwaGlsbCB2cyBmbGF0IGpvdXJuZXlzCiMgYmFzZWQgb24gZWxldmF0aW9uIG9mIHN0YXJ0IGFuZCBlbmQgc3RhdGlvbnMKCiMgNjg2MjIgZG93bmhpbGwgam91cm5leXMgNTUlCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihlbGV2YXRpb25fZGlmZiA8IDApICU+JSAKICBjb3VudCgpCgo2ODYyMiAvIDEyNDQ0NiAqIDEwMAoKIyA0Mzc3NCB1cGhpbGwgam91cm5leXMgMzUlCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihlbGV2YXRpb25fZGlmZiA+IDApICU+JSAKICBjb3VudCgpCgo0Mzc3NCAvIDEyNDQ0NiAqIDEwMAoKIyAxMjA1MCBmbGF0IGpvdXJuZXlzIDkuNyUKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKGVsZXZhdGlvbl9kaWZmID09IDApICU+JSAKICBjb3VudCgpCgoxMjA1MCAvIDEyNDQ0NiAqIDEwMApgYGAKYGBge3J9CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihlbmRfc3RhdGlvbl9sb25naXR1ZGUgPj0gLTMpCiAgCmBgYAoKCgojIyMgSm91cm5leXMgYmFzZWQgb24gd2VhdGhlcgoKQWNjb3JkaW5nIHRvIHd3dy5zdGF0aXN0YS5jb20gIkEgcmFpbmRheSBpcyB3aGVuIG9uZSBtaWxsaW1ldHJlIG9yIG1vcmUgb2YgcmFpbiBvY2N1cnMgaW4gYSBkYXkuIiBCYXNlZCBvbiB0aGlzIEkgaGF2ZSBjbGFzc2lmaWVkIHJhaW55IGRheXMgYXMgZGF5cyB3aGVyZSByYWluZmFsbCBhcyByZWNvcmRlZCBieSB3d3cucG93ZXIubGFyYy5uYXNhLmdvdi8gd2FzIGVxdWFsIHRvIG9yIG92ZXIgMW1tIGluIEVkaW5idXJnaC4KCgpgYGB7cn0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgc2VsZWN0KHN0YXJ0X2RhdGUsIHJhaW5mYWxsX21tKSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21fbGluZShhZXMoc3RhcnRfZGF0ZSwgcmFpbmZhbGxfbW0pLCBjb2wgPSAiYmx1ZSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAxLCBjb2w9IiNGMjdGMUIiKSArCiAgbGFicyh4ID0gIlxuRGF0ZSIsCiAgICAgICB5ID0gIlJhaW5mYWxsIChtbSlcbiIsCiAgICAgICB0aXRsZSA9ICJFZGluYnVyZ2gncyBkYWlseSByYWluZmFsbCBpbiAyMDE5IiwKICAgICAgIHN1YnRpdGxlID0gIihPcmFuZ2UgbGluZSBhdCAxbW0sIGFib3ZlIHdoaWNoIHdlIGNsYXNzIGFzIHJhaW55IGRheSlcbiIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpCmBgYAoKIyMjIEh5cG90aGVzaXMgVGVzdAoKYGBge3J9CiMgSW5kZXBlbmRlbmNlIEh5cG90aGVzaXMKIyDOsSA9IDAuMDUKIyBIMCAtIHVwaGlsbCBqb3VybmV5cyBtYWtlcyBubyBkaWZmZXJlbmNlIHRvIGJpa2UgaGlyZXMKIyBIMSAtIHVwaGlsbCBqb3VybmV5cyBoYXZlIGFuIGltcGFjdCBvbiBiaWtlIGhpcmVzCgojIG9yZ2FuaXNlIHRoZSBkYXRhIHNvIEkgaGF2ZSBhbiB1cGhpbGwgY29sdW1uIHdpdGggYSBsb2dpY2FsIG91dHB1dCBUUlVFL0ZBTFNFIGlmIHRoZSBlbGV2YXRpb24gY2hhbmdlIHdhcyBwb3NpdGl2ZQojIGFsc28gY291bnQgdGhlIG51bWJlciBvZiBqb3VybmV5cyB0aGF0IG9jY3VycmVkIG9uIGVhY2ggZGF5CnVwaGlsbCA8LSBoaXJlc18yMDE5X2NsZWFuICU+JQogIGdyb3VwX2J5KHN0YXJ0X2RhdGUpICU+JSAKICBtdXRhdGUodXBoaWxsID0gZWxldmF0aW9uX2RpZmYgPiAwKSAlPiUKICBzZWxlY3Qoc3RhcnRfZGF0ZSwgdXBoaWxsKSAlPiUgCiAgY291bnQoc3RhcnRfZGF0ZSwgdXBoaWxsKQoKIyBjcmVhdGUgYSBudWxsIGRpc3RyaWJ1dGlvbiBwZXJtdXRpbmcgdGhlIFRydWUgYW5kIEZhbHNlIHZhbHVlcyBvbiB3aGV0aGVyIHRoZSBqb3VybmV5IHdhcyB1cGhpbGwgb3Igbm90CiMgZG8gMTBrIHJlcHMgYW5kIGNoZWNrIHRoZSBkaWZmZXJlbmNlIGluIG1lYW5zIG9mIHRoZSBncm91cHMKbnVsbF9kaXN0cmlidXRpb24gPC0gdXBoaWxsICU+JSAKICBzcGVjaWZ5KG4gfiB1cGhpbGwpICU+JQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lIAogIGdlbmVyYXRlKHJlcHMgPSAxMDAwMCwgdHlwZSA9ICJwZXJtdXRlIikgJT4lIAogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoIlRSVUUiLCAiRkFMU0UiKSkgCgojIGNyZWF0ZSBhbiBvYnNlcnZlZCBzdGF0Cm9ic2VydmVkX3N0YXQgPC0gdXBoaWxsICU+JSAKICBzcGVjaWZ5KG4gfiB1cGhpbGwpICU+JQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoIlRSVUUiLCAiRkFMU0UiKSkgCgojIHBsb3Qgb2JzZXJ2ZWQgc3RhdCBvbiB0aGUgbnVsbCBkaXN0cmlidXRpb24KbnVsbF9kaXN0cmlidXRpb24gJT4lCiAgdmlzdWFsaXNlKCkgKwogIHNoYWRlX3BfdmFsdWUob2JzX3N0YXQgPSBvYnNlcnZlZF9zdGF0LCBkaXJlY3Rpb24gPSAibGVmdCIpCgojIGNhbGN1bGF0ZSB0aGUgcC12YWx1ZSBhbmQgY29tcGFyZSB0byDOsSB2YWx1ZQpwX3ZhbHVlIDwtIG51bGxfZGlzdHJpYnV0aW9uICU+JQogIGdldF9wX3ZhbHVlKG9ic19zdGF0ID0gb2JzZXJ2ZWRfc3RhdCwgZGlyZWN0aW9uID0gImxlZnQiKQoKcF92YWx1ZQpgYGAKCgpgYGB7cn0KIyBoeXBvdGhlc2lzIHRlc3QKIyDOsSA9IDAuMDUKIyBIMCAtIFJhaW4gbWFrZXMgbm8gZGlmZmVyZW5jZSB0byBiaWtlIGhpcmVzCiMgSDEgLSBSYWluIGhhcyBhbiBpbXBhY3Qgb24gYmlrZSBoaXJlcwojIFR5cGUgb2YgdGVzdCBpcyBvbmUtc2FtcGxlIHByb3BvcnRpb24sIHJpZ2h0LXNpZGVkLgojIAojIHAgdmFsdWUgPSAwIAojIAojIFRoZSBwLXZhbHVlIGJlaW5nIG5lYXIgdG8gMCBtZWFucyBpdCBpcyBsZXNzIHRoYW4gzrEsIGFuZCBzbyB3ZSBzaG91bGQgcmVqZWN0IEgwIGJhc2VkIG9uIG91ciBkYXRhLiBUaGUgcmVzdWx0IGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgaW4gZmF2b3VyIG9mIEgxLCB0aGF0IHJhaW4gbWF5IGltcGFjdCBiaWtlIGhpcmUgbnVtYmVycy4KCiMgcmFpbl9kYXkgPC0gaGlyZXNfMjAxOV9jbGVhbiAlPiUKIyAgIGdyb3VwX2J5KHN0YXJ0X2RhdGUpICU+JSAKIyAgIG11dGF0ZShyYWluX2RheSA9IHJhaW5mYWxsX21tID49IDEpICU+JSAKIyAgIHNlbGVjdChzdGFydF9kYXRlLCByYWluX2RheSkgJT4lIAojICAgY291bnQoc3RhcnRfZGF0ZSwgcmFpbl9kYXkpCiMgCiMgbnVsbF9kaXN0cmlidXRpb24gPC0gcmFpbl9kYXkgJT4lCiMgICBzcGVjaWZ5KHJlc3BvbnNlID0gcmFpbl9kYXksIHN1Y2Nlc3MgPSAiVFJVRSIpICU+JQojICAgaHlwb3RoZXNpemUobnVsbCA9ICJwb2ludCIsIHAgPSAwLjA1KSAlPiUKIyAgIGdlbmVyYXRlKHJlcHMgPSAxMDAwMCwgdHlwZSA9ICJkcmF3IikgJT4lCiMgICBjYWxjdWxhdGUoc3RhdCA9ICJwcm9wIikKIyAKIyBvYnNfc3RhdCA8LSByYWluX2RheSAlPiUKIyAgIHNwZWNpZnkocmVzcG9uc2UgPSByYWluX2RheSwgc3VjY2VzcyA9ICJUUlVFIikgJT4lCiMgICBjYWxjdWxhdGUoc3RhdCA9ICJwcm9wIikKIyAKIyBudWxsX2Rpc3RyaWJ1dGlvbiAlPiUKIyAgIHZpc3VhbGlzZSgpICsKIyAgIHNoYWRlX3BfdmFsdWUoZGlyZWN0aW9uID0gInJpZ2h0Iiwgb2JzX3N0YXQgPSBvYnNfc3RhdCkKIyAKIyBudWxsX2Rpc3RyaWJ1dGlvbiAlPiUKIyAgIGdldF9wX3ZhbHVlKGRpcmVjdGlvbiA9ICJyaWdodCIsIG9ic19zdGF0ID0gb2JzX3N0YXQpCgpgYGAKCmBgYHtyfQojIGJvb3RzdHJhcHBlZCBoeXBvdGhlc2lzCiMgzrEgPSAwLjA1CiMgSDAgLSBSYWluIG1ha2VzIG5vIGRpZmZlcmVuY2UgdG8gYmlrZSBoaXJlcwojIEgxIC0gUmFpbiBoYXMgYW4gaW1wYWN0IG9uIGJpa2UgaGlyZXMKCiMgcmFpbl9kYXlfZmxhZyA8LSByYWluX2RheSAlPiUKIyAgIG11dGF0ZShyYWluX2RheV9mbGFnID0gaWZfZWxzZShyYWluX2RheSA9PSAiVFJVRSIsIDEsIDApKQojIAojIG51bGxfZGlzdHJpYnV0aW9uIDwtIHJhaW5fZGF5X2ZsYWcgJT4lCiMgICBzcGVjaWZ5KHJlc3BvbnNlID0gcmFpbl9kYXlfZmxhZykgJT4lCiMgICBoeXBvdGhlc2l6ZShudWxsID0gInBvaW50IiwgbXUgPSAwLjA1KSAlPiUKIyAgIGdlbmVyYXRlKHJlcHMgPSAxMDAwMCwgdHlwZSA9ICJib290c3RyYXAiKSAlPiUKIyAgIGNhbGN1bGF0ZShzdGF0ID0gIm1lYW4iKQojIAojIG51bGxfZGlzdHJpYnV0aW9uICU+JQojICAgdmlzdWFsaXNlKCkgKwojICAgc2hhZGVfcF92YWx1ZShkaXJlY3Rpb24gPSAicmlnaHQiLCBvYnNfc3RhdCA9IG9ic19zdGF0KQojIAojIG51bGxfZGlzdHJpYnV0aW9uICU+JQojICAgZ2V0X3BfdmFsdWUoZGlyZWN0aW9uID0gInJpZ2h0Iiwgb2JzX3N0YXQgPSBvYnNfc3RhdCkKYGBgCgojIyMgSW5kZXBlbmRlbmNlIEh5cG90aGVzaXMgVGVzdCBPbiBSYWlueSBkYXkgZGF0YQoKRG9lcyBhIHJhaW55IGRheSBoYXZlIGFuIGVmZmVjdCBvbiBiaWtlIGhpcmVzCgrOsSA9IDAuMDUKSDAgLSBSYWluIG1ha2VzIG5vIGRpZmZlcmVuY2UgdG8gYmlrZSBoaXJlcwpIMSAtIFJhaW4gaGFzIGFuIGltcGFjdCBvbiBiaWtlIGhpcmVzCgpUaGUgcC12YWx1ZSDiiaQgzrEsIHNvIEkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgSDAgaW4gZmF2b3VyIG9mIHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIEgxLCAKdGhhdCByYWluIF9tYXlfIGhhdmUgYW4gZWZmZWN0IG9uIGJpa2UgaGlyZXMuCgpgYGB7cn0KIyBJbmRlcGVuZGVuY2UgSHlwb3RoZXNpcwojIM6xID0gMC4wNQojIEgwIC0gUmFpbiBtYWtlcyBubyBkaWZmZXJlbmNlIHRvIGJpa2UgaGlyZXMKIyBIMSAtIFJhaW4gaGFzIGFuIGltcGFjdCBvbiBiaWtlIGhpcmVzCgojIG9yZ2FuaXNlIHRoZSBkYXRhIHNvIEkgaGF2ZSBhIHJhaW5fZGF5IGNvbHVtbiB3aXRoIGEgbG9naWNhbCBvdXRwdXQgVFJVRS9GQUxTRSBpZiBpdCByYWluZWQgdGhhdCBkYXkKIyBhbHNvIGNvdW50IHRoZSBudW1iZXIgb2Ygam91cm5leXMgdGhhdCBvY2N1cnJlZCBvbiBlYWNoIGRheQpyYWluX2RheSA8LSBoaXJlc18yMDE5X2NsZWFuICU+JQogIGdyb3VwX2J5KHN0YXJ0X2RhdGUpICU+JSAKICBtdXRhdGUocmFpbl9kYXkgPSByYWluZmFsbF9tbSA+PSAxKSAlPiUgCiAgc2VsZWN0KHN0YXJ0X2RhdGUsIHJhaW5fZGF5KSAlPiUgCiAgY291bnQoc3RhcnRfZGF0ZSwgcmFpbl9kYXkpCgojIGNyZWF0ZSBhIG51bGwgZGlzdHJpYnV0aW9uIHBlcm11dGluZyB0aGUgVHJ1ZSBhbmQgRmFsc2UgdmFsdWVzIG9uIHdoZXRoZXIgaXQgcmFpbmVkCiMgZG8gMTBrIHJlcHMgYW5kIGNoZWNrIHRoZSBkaWZmZXJlbmNlIGluIG1lYW5zIG9mIHRoZSBncm91cHMKbnVsbF9kaXN0cmlidXRpb24gPC0gcmFpbl9kYXkgJT4lIAogIHNwZWNpZnkobiB+IHJhaW5fZGF5KSAlPiUKICBoeXBvdGhlc2l6ZShudWxsID0gImluZGVwZW5kZW5jZSIpICU+JSAKICBnZW5lcmF0ZShyZXBzID0gMTAwMDAsIHR5cGUgPSAicGVybXV0ZSIpICU+JSAKICBjYWxjdWxhdGUoc3RhdCA9ICJkaWZmIGluIG1lYW5zIiwgb3JkZXIgPSBjKCJUUlVFIiwgIkZBTFNFIikpIAoKIyBjcmVhdGUgYW4gb2JzZXJ2ZWQgc3RhdApvYnNlcnZlZF9zdGF0IDwtIHJhaW5fZGF5ICU+JSAKICBzcGVjaWZ5KG4gfiByYWluX2RheSkgJT4lCiAgY2FsY3VsYXRlKHN0YXQgPSAiZGlmZiBpbiBtZWFucyIsIG9yZGVyID0gYygiVFJVRSIsICJGQUxTRSIpKSAKCiMgcGxvdCBvYnNlcnZlZCBzdGF0IG9uIHRoZSBudWxsIGRpc3RyaWJ1dGlvbgpudWxsX2Rpc3RyaWJ1dGlvbiAlPiUKICB2aXN1YWxpc2UoKSArCiAgc2hhZGVfcF92YWx1ZShvYnNfc3RhdCA9IG9ic2VydmVkX3N0YXQsIGRpcmVjdGlvbiA9ICJsZWZ0IikKCiMgY2FsY3VsYXRlIHRoZSBwLXZhbHVlIGFuZCBjb21wYXJlIHRvIM6xIHZhbHVlCnBfdmFsdWUgPC0gbnVsbF9kaXN0cmlidXRpb24gJT4lCiAgZ2V0X3BfdmFsdWUob2JzX3N0YXQgPSBvYnNlcnZlZF9zdGF0LCBkaXJlY3Rpb24gPSAibGVmdCIpCgpwX3ZhbHVlCgpgYGAKClJhaW55IERheXMgaW4gMjAxOSA9IDE4MQpSYWlueSBqb3VybmV5cyA9IDU4MDczICg0Ni43JSkKTm9uIHJhaW55IGpvdXJuZXlzID0gNjYzNzMgKDUzLjMlKQoKYGBge3J9CiMgY291bnQgdGhlIG51bWJlciBvZiBkYXlzIHdpdGggcmFpbmZhbGwgZXF1YWwgdG8gb3Igb3ZlciAxbW0KcmFpbl8yMDE5X2NsZWFuICU+JSAKICBmaWx0ZXIocmFpbmZhbGxfbW0gPj0gMSkgJT4lIAogIGNvdW50KCkKCiMgam91cm5leXMgYmFzZWQgb24gcmFpbmZhbGwKIyBiYXNlZCBvbiBkYWlseSBwcmVjaXBpdGF0aW9uCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihyYWluZmFsbF9tbSA+PSAxKSAlPiUgCiAgY291bnQoKQoKNTgwNzMgLyAxMjQ0NDYgKiAxMDAKCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihyYWluZmFsbF9tbSA8IDEpICU+JSAKICBjb3VudCgpCgo2NjM3MyAvIDEyNDQ0NiAqIDEwMApgYGAKCgojIyMgVGltZSBvZiBEYXkgYW5hbHlzaXMKCkd5bSBCdW5uaWVzIC0gNWFtIHRvIDdhbTogICAgICAgICAgIDI0MTkgICAxNy41NCBtaW5zICAgCk1vcm5pbmcgQ29tbXV0ZXJzIC0gN2FtIHRvIDlhbTogICAgIDEyNDUyICAxNy44NyBtaW5zICAgIApEYXkgVHJpcHBlcnMgLSA5YW0gdG8gNXBtOiAgICAgICAgICA2Njg4MCAgMjkuNzUgbWlucyAgICAKSG9tZXdhcmQgQm91bmRlcnMgLSA1cG0gdG8gNi4zMHBtOiAgMTQ5NjEgIDIzLjg2IG1pbnMgICAgCkV2ZW5pbmcgTW92ZXJzIC0gNi4zMHBtIHRvIDEwcG06ICAgIDE2ODE1ICAyMy41MCBtaW5zICAgIApQdWIgUG9uaWVzIC0gMTBwbSB0byA1YW06ICAgICAgICAgICAxMDkxOSAgMjMuMDcgbWlucyAgIAoKQXZlcmFnZSBqb3VybmV5IHRpbWUgb3ZlcmFsbCBpcyAyNi4xOCBtaW51dGVzCgpNb3N0IHBvcHVsYXIgaG91ciBpcyBmcm9tIDRwbSB0byA1cG0gMTIyNzkgam91cm5leXMgYXZlcmFnZSB0aW1lIDI0LjI3IG1pbnMuCgpgYGB7cn0KIyBwdWIgcG9uaWVzIGZyb20gdGhlIG5pZ2h0IGJlZm9yZQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoc3RhcnRfdGltZSA9IGFzLmNoYXJhY3RlcihzdGFydF90aW1lKSwgZW5kX3RpbWUgPSBhcy5jaGFyYWN0ZXIoZW5kX3RpbWUpKSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3RpbWUgPCAiMDU6MDA6MDAiIHwgc3RhcnRfdGltZSA+PSAiMjI6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBHeW0gQnVubmllcyAtIGJlZm9yZSA3YW0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID4gIjA1OjAwOjAwIiwgc3RhcnRfdGltZSA8PSAiMDc6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBNb3JuaW5nIENvbW11dGVycyAtIDdhbSB0byA5YW0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID4gIjA3OjAwOjAwIiwgc3RhcnRfdGltZSA8PSAiMDk6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBEYXkgVHJpcHBlcnMgLSA5YW0gdG8gNXBtCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIG11dGF0ZShzdGFydF90aW1lID0gYXMuY2hhcmFjdGVyKHN0YXJ0X3RpbWUpLCBlbmRfdGltZSA9IGFzLmNoYXJhY3RlcihlbmRfdGltZSkpICU+JSAKICBmaWx0ZXIoc3RhcnRfdGltZSA+ICIwOTowMDowMCIsIHN0YXJ0X3RpbWUgPCAiMTc6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBIb21ld2FyZCBCb3VuZGVycyAtIDVwbSB0byA2LjMwcG0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID49ICIxNzowMDowMCIsIHN0YXJ0X3RpbWUgPD0gIjE4OjMwOjAwIikgJT4lIAogIG11dGF0ZShtZWFuX2R1cmF0aW9uID0gcm91bmQobWVhbihkdXJhdGlvbiksIDIpKSAlPiUgCiAgY291bnQobWVhbl9kdXJhdGlvbikKCiMgRXZlbmluZyBNb3ZlcnMgLSA2LjMwcG0gdG8gMTBwbQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoc3RhcnRfdGltZSA9IGFzLmNoYXJhY3RlcihzdGFydF90aW1lKSwgZW5kX3RpbWUgPSBhcy5jaGFyYWN0ZXIoZW5kX3RpbWUpKSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3RpbWUgPiAiMTg6MzA6MDAiLCBzdGFydF90aW1lIDwgIjIyOjAwOjAwIikgJT4lIAogIG11dGF0ZShtZWFuX2R1cmF0aW9uID0gcm91bmQobWVhbihkdXJhdGlvbiksIDIpKSAlPiUgCiAgY291bnQobWVhbl9kdXJhdGlvbikKCiMgUHViIFBvbmllcyAtIDEwcG0gdG8gTWlkbmlnaHQKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID49ICIyMjowMDowMCIpICU+JSAKICBtdXRhdGUobWVhbl9kdXJhdGlvbiA9IHJvdW5kKG1lYW4oZHVyYXRpb24pLCAyKSkgJT4lIAogIGNvdW50KG1lYW5fZHVyYXRpb24pCgojIGhpcmVzIGF0IG1vc3QgcG9wdWxhciB0aW1lIG9mIDRwbQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoc3RhcnRfdGltZSA9IGFzLmNoYXJhY3RlcihzdGFydF90aW1lKSwgZW5kX3RpbWUgPSBhcy5jaGFyYWN0ZXIoZW5kX3RpbWUpKSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3RpbWUgPj0gIjE2OjAwOjAwIiwgc3RhcnRfdGltZSA8ICIxNzowMDowMCIpICU+JSAKICBtdXRhdGUobWVhbl9kdXJhdGlvbiA9IHJvdW5kKG1lYW4oZHVyYXRpb24pLCAyKSkgJT4lIAogIGNvdW50KG1lYW5fZHVyYXRpb24pCgojIEF2ZXJhZ2Ugam91cm5leSBsZW5ndGgKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKYGBgCgoKYGBge3J9CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIHNlbGVjdChzdGFydF90aW1lKSAlPiUKICBncm91cF9ieShzdGFydF90aW1lKSAlPiUgCiAgY291bnQoKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHN0YXJ0X3RpbWUpLCBjb2wgPSAid2hpdGUiLCBmaWxsID0gIiNGMjdGMUIiKSArCiAgbGFicyh4ID0gIlxuVGltZSBvZiBEYXkiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgSm91cm5leXNcbiIsCiAgICAgICB0aXRsZSA9ICJTdGFydCB0aW1lIG9mIGpvdXJuZXlzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKYGBgCmBgYHtyfQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoc3RhcnRfaG91ciA9IGhvdXIoc3RhcnRfdGltZSksIC5iZWZvcmUgPSAyKSAlPiUgCiAgZ3JvdXBfYnkoc3RhcnRfaG91cikgJT4lIAogIGNvdW50KHN0YXJ0X2hvdXIpICU+JSAKICBnZ3Bsb3QoKSArCiAgI2dlb21fcmVjdChhZXMoeG1pbj0wLCB4bWF4PTcsIHltaW49MCwgeW1heD1JbmYpLCBmaWxsID0gIiNGMjdGMUIiLCBhbHBoYSA9IDAuMSkgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMCwgeG1heCA9IDUsIHltaW4gPSAwLCB5bWF4ID0gSW5mLCBmaWxsID0gIiM1QTRGRjUiLCBhbHBoYSA9IC45KSArCiAgIyBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA1LCB4bWF4ID0gNywgeW1pbiA9IDAsIHltYXggPSBJbmYsIGZpbGwgPSAiI0ZGRkI4NSIsIGFscGhhID0gLjcpICsKICAjIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDcsIHhtYXggPSA5LCB5bWluID0gMCwgeW1heCA9IEluZiwgZmlsbCA9ICIjRkZFOTMwIiwgYWxwaGEgPSAuNikgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gOSwgeG1heCA9IDE3LCB5bWluID0gMCwgeW1heCA9IEluZiwgZmlsbCA9ICIjRjI3RjFCIiwgYWxwaGEgPSAuNCkgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTcsIHhtYXggPSAxOC41LCB5bWluID0gMCwgeW1heCA9IEluZiwgZmlsbCA9ICIjREU2RENDIiwgYWxwaGEgPSAuNCkgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMTguNSwgeG1heCA9IDIyLCB5bWluID0gMCwgeW1heCA9IEluZiwgZmlsbCA9ICIjOUQ4NEY1IiwgYWxwaGEgPSAuNykgKwogICMgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gMjIsIHhtYXggPSAyMywgeW1pbiA9IDAsIHltYXggPSBJbmYsIGZpbGwgPSAiIzVBNEZGNSIsIGFscGhhID0gLjkpICsKICBnZW9tX3BvaW50KGFlcyhzdGFydF9ob3VyLCBuKSwgY29sb3IgPSAiI0YyN0YxQiIpICsKICBnZW9tX2xpbmUoYWVzKHN0YXJ0X2hvdXIsIG4pLCBjb2xvciA9ICIjRjI3RjFCIiwgYWxwaGEgPSAwLjUpICsKICAgIGxhYnMoeCA9ICJcblN0YXJ0IGhvdXIiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgSm91cm5leXNcbiIsCiAgICAgICB0aXRsZSA9ICJTVEFSVCBUSU1FIE9GIEpPVVJORVlTXG4iKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKDAsLjUpLCBsaW1pdHMgPSBjKDA6MjMpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhbWlseT0iUHJveGltYSBOb3ZhIiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFtaWx5PSJQcm94aW1hIE5vdmEiLCBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiIzhDOEM4QyIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ICIjOEM4QzhDIiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0gIiM4QzhDOEMiKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiIzhDOEM4QyIpKQpgYGAKYGBge3J9CiMgaGVhdG1hcCBvZiBzdGFydCB0aW1lcwpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoc3RhcnRfaG91ciA9IGhvdXIoc3RhcnRfdGltZSksIC5iZWZvcmUgPSAyKSAlPiUgCiAgY291bnQoc3RhcnRfZGF0ZSwgc3RhcnRfaG91cikgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3RpbGUoYWVzKHN0YXJ0X2RhdGUsIHN0YXJ0X2hvdXIsIGZpbGwgPSBuKSkgKwogIGxhYnMoeCA9ICJcbkRhdGUiLAogICAgICAgeSA9ICJTdGFydCB0aW1lXG4iLAogICAgICAgdGl0bGUgPSAiU1RBUlQgVElNRSBPRiBKT1VSTkVZUyBIRUFUTUFQXG4iKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhbWlseT0iUHJveGltYSBOb3ZhIiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFtaWx5PSJQcm94aW1hIE5vdmEiLCBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiIzhDOEM4QyIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ICIjOEM4QzhDIiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0gIiM4QzhDOEMiKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiIzhDOEM4QyIpKQpgYGAKCgoKYGBge3J9CiMgdHJ5aW5nIGEgcmFzdGVyIGltYWdlIG9mIGVsZXZhdGlvbgoKZWRpIDwtIHN0X3JlYWQoJy4uL3Jhd19kYXRhL0VkaW5idXJnaF9XYXJkX0JvdW5kYXJpZXMvRWRpbmJ1cmdoX1dhcmRfQm91bmRhcmllcy5zaHAnLCAiRWRpbmJ1cmdoX1dhcmRfQm91bmRhcmllcyIpCgpzdF91bmlvbihlZGkpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9yYXN0ZXIoZGF0YSA9IG5ld19lbGV2YXRpb25fcmFzdGVyLCBhZXMoeCA9IHgsIHkgPSB5KSkgKwogIGdlb21fc2YoZGF0YSA9IGVkaSwgY29sb3IgPSAicmVkIikgKwogIGNvb3JkX3NmKCkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKwogIGxhYnModGl0bGUgPSAiICIsIHggPSAiICIsIHkgPSAiICIsIGZpbGwgPSAiICIpCgoKCgoKcGxvdChlbGV2YXRpb25fcmFzdGVyLCAKICAgICBtYWluID0gIkVsZXZhdGlvbiBsZXZlbHMgYWNyb3NzIEVkaW5idXJnaCBpbiBtZXRyZXMiLAogICAgIGtleSA9ICJtYXBfZGF0YSIpCmBgYAoK